/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.xpath.model;

import offset.nodes.client.model.NodeTypes;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ResourceBundle;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JMenuBar;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.text.Document;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import offset.nodes.client.model.Server;
import offset.nodes.client.model.TreeNodeUserObject;
import offset.nodes.client.tree.model.TreeConfiguration;
import offset.nodes.client.tree.model.TreeNodeType;
import offset.nodes.client.virtual.model.GetSchemas;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeDefinition;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeReader;


/**
 *
 * @author Walter Lütgenau
 */
public class ValueConstraintConfiguration implements TreeConfiguration {

    JTree tree;
    Server server;
    TreeNodeType[] nodeTypes;
    NodeTypes types;
    boolean enabled = false;

    public ValueConstraintConfiguration(Server server) {
        this.server = server;
        this.nodeTypes = new TreeNodeType[] {
            new And(), new Or(), new Expression()
        };
     }

    public void enable() {
        this.enabled = true;
    }

    public NodeTypeDefinition[] initTypes() {
        GetSchemas.Request request = new GetSchemas.Request();
        GetSchemas.Response response = null;
        try {
            response = (GetSchemas.Response) server.sendRequest(request);
            InputStream in = new ByteArrayInputStream(response.getSchemaXml().getBytes());
            NodeTypeDefinition[] definitions = NodeTypeReader.read(in);

            return definitions;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public void init(JTree tree, JToolBar toolBar, JMenuBar menu) {
        this.types = new NodeTypes(initTypes());
        this.tree = tree;
        setupTree();
    }

    protected void setupTree() {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(getNodeTypes()[0].createUserObject());
        ((DefaultTreeModel) tree.getModel()).setRoot(root);
        tree.setSelectionRow(0);
    }

    public Object getResult() {
        return ((DefaultTreeModel) tree.getModel()).getRoot();
    }

    protected TreeNodeType getNodeType(String name) {
        for (int i = 0; i < nodeTypes.length; i++) {
            if (nodeTypes[i].getName().equals(name)) {
                return nodeTypes[i];
            }
        }
        return null;
    }

    public void insertNodeAt(DefaultMutableTreeNode parent, int position, String typeName) {
        DefaultMutableTreeNode insert = new DefaultMutableTreeNode();

        TreeNodeType nodeType = getNodeType(typeName);
        if (nodeType == null) {
            return;
        }

        insert.setUserObject(nodeType.createUserObject());
        ((DefaultTreeModel) tree.getModel()).insertNodeInto(insert, parent, position);

        TreePath childPath = new TreePath(insert.getPath());
        tree.setSelectionPath(childPath);
    }

    public void removeNode(DefaultMutableTreeNode remove) {
        int[] selected = tree.getSelectionRows();
        ((DefaultTreeModel) tree.getModel()).removeNodeFromParent(remove);
        if (selected.length > 0 && selected[0] > 0) {
            tree.setSelectionRow(selected[0] - 1);
        }
    }

    public void writeTextualRepresentation(Document document, ResourceBundle bundle) {
        // todo
    }

    public TreeConfiguration getModel() {
        return this;
    }

    class And implements TreeNodeType {

        Icon andIcon = new ImageIcon(ValueConstraintConfiguration.class.getResource("/offset/nodes/client/view/resources/and.png"));

        public String getName() {
            return AndNode.TYPE_AND;
        }

        public Icon getIcon() {
            return andIcon;
        }

        public TreeNodeUserObject createUserObject() {
            return new AndNode();
        }
   
        public boolean canAccept(String typeName) {
            return enabled;
        }
 }

    class Or implements TreeNodeType {

        Icon orIcon = new ImageIcon(ValueConstraintConfiguration.class.getResource("/offset/nodes/client/view/resources/or.png"));

        public String getName() {
            return OrNode.TYPE_OR;
        }

        public Icon getIcon() {
            return orIcon;
        }

        public TreeNodeUserObject createUserObject() {
            return new OrNode();
        }
   
        public boolean canAccept(String typeName) {
            return enabled;
        }
 }

    class Expression implements TreeNodeType {

        Icon expressionIcon = new ImageIcon(ValueConstraintConfiguration.class.getResource("/offset/nodes/client/view/resources/sc_property.png"));

        public String getName() {
            return ExpressionNode.TYPE_EXPRESSION;
        }

        public Icon getIcon() {
            return expressionIcon;
        }

        public TreeNodeUserObject createUserObject() {
            return ExpressionNode.createEmpyExpression();
        }
   
        public boolean canAccept(String typeName) {
            return false;
        }
 }


    public TreeNodeType[] getNodeTypes() {
        return nodeTypes;
    }
}
